package com.example.drugaiservice.service.impl;

import com.baidubce.qianfan.Qianfan;
import com.baidubce.qianfan.model.chat.ChatResponse;
import com.example.drugaiservice.common.utils.*;
import com.example.drugaiservice.pojo.dto.HospDTO;
import com.example.drugaiservice.pojo.entity.Case;
import com.example.drugaiservice.pojo.entity.Drug;
import com.example.drugaiservice.pojo.entity.Hosp;
import com.example.drugaiservice.pojo.entity.Hospital;
import com.example.drugaiservice.pojo.vo.HospVO;
import com.example.drugaiservice.service.AskService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class AskServiceimpl implements AskService {
    @Value("${qianfan.ak}")
    private String ak;
    @Value("${qianfan.sk}")
    private String sk;
    private final RedisTemplate redisTemplate;
    private final SearchWords searchWords;
    private final BiaoGeApi biaoGeApi;
    private final WenZiApi wenZiApi;
    private final HospitalCSV csv;

    //定期存储数据加快访问速度
    private void saveDrug(Drug drug) {
        Duration ttl = Duration.ofDays(7);
        redisTemplate.opsForValue().set(drug.getName(), drug, ttl);
    }

    private Drug getDrug(String name) {
        return (Drug) redisTemplate.opsForValue().get(name);
    }

    //此方法为通过百度大模型进行药品问答
    public List<String> askS(String questions) {
        String myQuestion = "请分点简要说明" + questions + "的作用，不良反应，饮食建议，禁忌，药物相似药。要求每项尽量简短，并且你回答的数据必须" +
                "以作用：、不良反应：、饮食建议：、禁忌：、药物相似药：为开头";
        ChatResponse response = new Qianfan(ak,sk)
                .chatCompletion()
                .model("ERNIE-Bot") // 使用model指定预置模型
                // .endpoint("completions_pro") // 也可以使用endpoint指定任意模型 (二选一)
                .addMessage("user", myQuestion) // 添加用户消息 (此方法可以调用多次，以实现多轮对话的消息传递)
                .temperature(0.7) // 自定义超参数
                .execute(); // 发起请求
        String ans = response.getResult().replace("\n", "").replace("*","");
        log.info(ans);
        List<String> medicineInfoList = parseMedicineInfo(ans);
        return medicineInfoList;
    }

    //此方法为通过上传图片信息获取药品名称和药品信息
    @Override
    public Drug findPandReturnDrug(byte[] path) throws Exception {
        String json = wenZiApi.WenZiApi(path);//调用api
        ObjectMapper objectMapper = new ObjectMapper();
        JsonResponse response = objectMapper.readValue(json, JsonResponse.class);
        StringBuilder res = new StringBuilder();

        for (JsonResponse.Result.Line line : response.getResult().getLines()) {
            String text = line.getText();
            String eachRes = searchWords.search(text);
            if (res.isEmpty()) {
                log.info("比对结果为{}", eachRes);
                res.append(eachRes);
            }
        }
        log.info("药品为{}", res);
        Drug drug = getDrug(String.valueOf(res));
        if (drug == null) {
            drug = Drug.builder().name(res.toString()).intro(askS(res.toString())).build();
            saveDrug(drug);
            log.info("redis存入了新数据");
        } else {
            log.info("redis中存在数据，直接返回");
        }
        return drug;
    }

    //此方法为通过图片返回病例分析信息
    @Override
    public Case findPandReturnCase(byte[] path) throws Exception {
        String res=biaoGeApi.BiaoGeApi(path);
        return Case.builder().desc(res).build();
    }

    @Override
    public List<HospVO> findTop2(HospDTO hosp) {
        Hosp hosp1=new Hosp();
        BeanUtils.copyProperties(hosp,hosp1);
        List<Hosp> hosps = csv.HospCSV(hosp1);
        List<HospVO>vo=hosps.stream().
                map(setmeal -> {
                    HospVO v=new HospVO();
                    BeanUtils.copyProperties(setmeal,v);
                    return v;
                }).
                collect(Collectors.toList());
        return vo;
    }

    @Override
    public Hospital findPandReturnHospital(byte[] path) throws Exception {
        String json= wenZiApi.WenZiApi(path);
        ObjectMapper objectMapper = new ObjectMapper();
        JsonResponse response = objectMapper.readValue(json, JsonResponse.class);
        StringBuilder res = new StringBuilder();
        String texts="";
        for (JsonResponse.Result.Line line : response.getResult().getLines()) {
             texts += line.getText();
        }
        return Hospital.builder().desc(texts).build();
    }

    //此方法为通过输入名称查询药品名称和信息
    @Override
    public Drug NameReturnDrug(String name) throws JsonProcessingException {
        log.info("药品名称为{}", name);
        String res = searchWords.search(name);
        log.info("比对结果为{}", res);
        Drug drug = getDrug(String.valueOf(res));
        if (drug == null) {
            drug = Drug.builder().name(res).intro(askS(res)).build();
            saveDrug(drug);
            log.info("redis存入了新数据");
        } else {
            log.info("redis中存在数据，直接返回");
        }
        return drug;
    }

    //切割答案
    public List<String> parseMedicineInfo(String info) {
        List<String> medicineInfoList = new ArrayList<>();
        // 分割出“的作用：”之后的内容和“不良反应：”之前的内容
        String[] sections1 = info.split("作用：");
        String part1 = sections1[1].split("不良反应：")[0];
        medicineInfoList.add(part1.trim());
        // 分割出“不良反应：”之后的内容和“饮食建议：”之前的内容
        String[] sections2 = info.split("不良反应：");
        String part2 = sections2[1].split("饮食建议：")[0];
        medicineInfoList.add(part2.trim());
        // 分割出“不良反应：”之后的内容和“禁忌：”之前的内容
        String[] sections3 = info.split("饮食建议：");
        String part3 = sections3[1].split("禁忌：")[0];
        medicineInfoList.add(part3.trim());
        // 分割出“禁忌：”之后的内容和“药物相似药：”之前的内容
        String[] sections4 = info.split("禁忌：");
        String part4 = sections4[1].split("药物相似药：")[0];
        medicineInfoList.add(part4.trim());
        // 分割出“药物相似药：”之后的内容
        String[] sections5 = info.split("药物相似药：");
        medicineInfoList.add(sections5[1].trim());
        return medicineInfoList;
    }

}
